<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SimpleTest for PHP test suites</title>
<link rel="stylesheet" type="text/css" href="docs.css" title="Styles">
</head>
<body>
<div class="menu_back">
<div class="menu"><a href="index.html">SimpleTest</a> | <a
	href="overview.html">Overview</a> | <a
	href="unit_test_documentation.html">Unit tester</a> | <span
	class="chosen">Group tests</span> | <a
	href="mock_objects_documentation.html">Mock objects</a> | <a
	href="partial_mocks_documentation.html">Partial mocks</a> | <a
	href="reporter_documentation.html">Reporting</a> | <a
	href="expectation_documentation.html">Expectations</a> | <a
	href="web_tester_documentation.html">Web tester</a> | <a
	href="form_testing_documentation.html">Testing forms</a> | <a
	href="authentication_documentation.html">Authentication</a> | <a
	href="browser_documentation.html">Scriptable browser</a></div>
</div>
<h1>Test suite documentation</h1>
This page...
<ul>
	<li>Different ways to <a href="#group">group tests</a> together.</li>
	<li>Combining group tests into <a href="#higher">larger groups</a>.
	</li>
	<li>Integrating <a href="#legacy">legacy test cases</a> from other
	types of PHPUnit.</li>
</ul>
<div class="content">
<p><a class="target" name="group">
<h2>Grouping tests into suites</h2>
</a></p>
<p>To run test cases as part of a group, the test cases should
really be placed in files without the runner code...
<pre>
<strong>&lt;?php
    require_once('../classes/io.php');

    class FileTester extends UnitTestCase {
        ...
    }

    class SocketTester extends UnitTestCase {
        ...
    }
?&gt;</strong>
</pre> As many cases as needed can appear in a single file. They should
include any code they need, such as the library being tested, but none
of the simple test libraries.
</p>
<p>If you have extended any test cases, you can include them as
well. In PHP 4...
<pre>
&lt;?php
    require_once('../classes/io.php');
<strong>
    class MyFileTestCase extends UnitTestCase {
        ...
    }
    SimpleTest::ignore('MyFileTestCase');</strong>

    class FileTester extends MyFileTestCase { ... }

    class SocketTester extends UnitTestCase { ... }
?&gt;
</pre> The <span class="new_code">FileTester</span> class does not contain any
actual tests, but is a base class for other test cases. For this reason
we use the <span class="new_code">SimpleTestOptions::ignore()</span>
directive to tell the upcoming group test to ignore it. This directive
can appear anywhere in the file and works when a whole file of test
cases is loaded (see below).
</p>
<p>If you are using PHP 5, you do not need this special directive at
all. Simply mark any test cases that should not be run as abstract...
<pre>
<strong>abstract</strong> class MyFileTestCase extends UnitTestCase {
    ...
}

class FileTester extends MyFileTestCase { ... }

class SocketTester extends UnitTestCase { ... }
</pre>
</p>
<p>We will call this sample <em>file_test.php</em>. Next we create a
group test file, called say <em>my_group_test.php</em>. You will think
of a better name I am sure.</p>
<p>We will add the test file using a safe method...
<pre>
&lt;?php
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');<strong>
    require_once('file_test.php');

    $test = &amp;new TestSuite('All file tests');
    $test-&gt;addTestCase(new FileTestCase());
    $test-&gt;run(new HtmlReporter());</strong>
?&gt;
</pre> This instantiates the test case before the test suite is run. This
could get a little expensive with a large number of test cases, and can
be surprising behaviour.
</p>
<p>The main problem is that for every test case that we add we will
have to <span class="new_code">require_once()</span> the test code file
and manually instantiate each and every test case.</p>
<p>We can save a lot of typing with...
<pre>
&lt;?php
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');

    $test = &amp;new TestSuite('All file tests');<strong>
    $test-&gt;addTestFile('file_test.php');</strong>
    $test-&gt;run(new HtmlReporter());
?&amp;gt;
</pre> What happens here is that the <span class="new_code">TestSuite</span>
class has done the <span class="new_code">require_once()</span> for us.
It then checks to see if any new test case classes have been created by
the new file and automatically adds them to the group test. Now all we
have to do is add each new file.
</p>
<p>No only that, but you can guarantee that the constructor is run
just before the first test method and, in PHP 5, the destructor is run
just after the last test method.</p>
<p>There are two things that could go wrong and which require
care...
<ol>
	<li>The file could already have been parsed by PHP, and so no new
	classes will have been added. You should make sure that the test cases
	are only included in this file and no others.</li>
	<li>New test case extension classes that get included will be
	placed in the group test and run also. You will need to add a <span
		class="new_code">SimpleTestOptions::ignore()</span> directive for
	these classes, or make sure that they are included before the <span
		class="new_code">TestSuite::addTestFile()</span> line, or make sure
	that they are abstract classes.</li>
</ol>
</p>

<p><a class="target" name="higher">
<h2>Composite suites</h2>
</a></p>
<p>The above method places all of the test cases into one large
group. For larger projects though this may not be flexible enough; you
may want to group the tests in all sorts of ways.</p>
<p>To get a more flexible group test we can subclass <span
	class="new_code">TestSuite</span> and then instantiate it as needed...

<pre>
&lt;?php
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');
    <strong>
    class FileTestSuite extends TestSuite {
        function FileTestSuite() {
            $this-&gt;TestSuite('All file tests');
            $this-&gt;addTestFile('file_test.php');
        }
    }</strong>
?&gt;
</pre> This effectively names the test in the constructor and then adds our
test cases and a single group below. Of course we can add more than one
group at this point. We can now invoke the tests from a separate runner
file... <pre>
&lt;?php
    require_once('file_test_suite.php');
    <strong>
    $test = &amp;new FileTestSuite();
    $test-&gt;run(new HtmlReporter());</strong>
?&gt;
</pre> ...or we can group them into even larger group tests. We can even mix
groups and test cases freely as long as we are careful about double
includes... <pre>
&lt;?php
    <strong>
    $test = &amp;new BigTestSuite('Big group');
    $test-&gt;addTestFile('file_test_suite.php');
    $test-&gt;addTestFile('some_test_case.php');</strong>
    $test-&gt;run(new HtmlReporter());
?&gt;
</pre> In the event of a double include, ony the first instance of the test
case will be run.
</p>
<p>If we still wish to run the original group test, and we don't
want all of these little runner files, we can put the test runner code
around guard bars when we create each group.
<pre>
&lt;?php
    class FileTestSuite extends TestSuite {
        function FileTestSuite() {
            $this-&gt;TestSuite('All file tests');
            $test-&gt;addTestFile('file_test.php');
        }
    }
    <strong>
    if (! defined('RUNNER')) {
        define('RUNNER', true);</strong>
        $test = &amp;new FileTestSuite();
        $test-&gt;run(new HtmlReporter());
    }
?&gt;
</pre> This approach requires the guard to be set when including the group
test file, but this is still less hassle than lots of separate runner
files. You include the same guard on the top level tests to make sure
that <span class="new_code">run()</span> will run once only from the top
level script that has been invoked. <pre>
&lt;?php<strong>
    define('RUNNER', true);</strong>
    require_once('file_test_suite.php');

    $test = &amp;new BigTestSuite('Big group');
    $test-&gt;addTestCase(new FileTestSuite());
    $test-&gt;addTestCase(...);
    $test-&gt;run(new HtmlReporter());
?&gt;
</pre> As with the normal test cases, a <span class="new_code">TestSuite</span>
can be loaded with the <span class="new_code">TestSuite::addTestFile()</span>
method. <pre>
&lt;?php
    define('RUNNER', true);

    $test = &amp;new BigTestSuite('Big group');<strong>
    $test-&gt;addTestFile('file_test_suite.php');
    $test-&gt;addTestFile(...);</strong>
    $test-&gt;run(new HtmlReporter());
?&gt;
</pre>
</p>

<p><a class="target" name="legacy">
<h2>Integrating legacy test cases</h2>
</a></p>
<p>If you already have unit tests for your code or are extending
external classes that have tests, it is unlikely that all of the test
cases are in SimpleTest format. Fortunately it is possible to
incorporate test cases from other unit testers directly into SimpleTest
group tests.</p>
<p>Say we have the following <a
	href="http://sourceforge.net/projects/phpunit">PhpUnit</a> test case in
the file <em>config_test.php</em>...
<pre>
<strong>class ConfigFileTest extends TestCase {
    function ConfigFileTest() {
        $this-&gt;TestCase('Config file test');
    }
    
    function testContents() {
        $config = new ConfigFile('test.conf');
        $this-&gt;assertRegexp('/me/', $config-&gt;getValue('username'));
    }
}</strong>
</pre> The group test can recognise this as long as we include the appropriate
adapter class before we add the test file... <pre>
&lt;?php
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');<strong>
    require_once('simpletest/adapters/phpunit_test_case.php');</strong>

    $test = &amp;new TestSuite('All file tests');<strong>
    $test-&gt;addTestFile('config_test.php');</strong>
    $test-&gt;run(new HtmlReporter());
?&gt;
</pre> There are only two adapters, the other is for the <a
	href="http://pear.php.net/manual/en/package.php.phpunit.php">PEAR</a>
1.0 unit tester... <pre>
&lt;?php
    require_once('simpletest/unit_tester.php');
    require_once('simpletest/reporter.php');<strong>
    require_once('simpletest/adapters/pear_test_case.php');</strong>

    $test = &amp;new TestSuite('All file tests');<strong>
    $test-&gt;addTestFile('some_pear_test_cases.php');</strong>
    $test-&gt;run(new HtmlReporter());
?&gt;
</pre> The PEAR test cases can be freely mixed with SimpleTest ones even in
the same test file, but you cannot use SimpleTest assertions in the
legacy test case versions. This is done as a check that you are not
accidently making your test cases completely dependent on SimpleTest.
You may want to do a PEAR release of your library for example, which
would mean shipping it with valid PEAR::PhpUnit test cases.
</p>

</div>
References and related information...
<ul>
	<li>SimpleTest project page on <a
		href="http://sourceforge.net/projects/simpletest/">SourceForge</a>.</li>
	<li>SimpleTest download page on <a
		href="http://www.lastcraft.com/simple_test.php">LastCraft</a>.</li>
</ul>
<div class="menu_back">
<div class="menu"><a href="index.html">SimpleTest</a> | <a
	href="overview.html">Overview</a> | <a
	href="unit_test_documentation.html">Unit tester</a> | <span
	class="chosen">Group tests</span> | <a
	href="mock_objects_documentation.html">Mock objects</a> | <a
	href="partial_mocks_documentation.html">Partial mocks</a> | <a
	href="reporter_documentation.html">Reporting</a> | <a
	href="expectation_documentation.html">Expectations</a> | <a
	href="web_tester_documentation.html">Web tester</a> | <a
	href="form_testing_documentation.html">Testing forms</a> | <a
	href="authentication_documentation.html">Authentication</a> | <a
	href="browser_documentation.html">Scriptable browser</a></div>
</div>
<div class="copyright">Copyright<br>
Marcus Baker 2006</div>
</body>
</html>
